﻿package com.bizmlib.framework.flashapp
{
	import flash.display.MovieClip;
	import flash.events.Event;
	
	import com.bizmlib.framework.flashapp;
	import com.bizmlib.framework.flashapp.mvc.*;
	
	
	public class FlashAppEngine extends MovieClip
	{
		private static var __instance:FlashAppEngine;
		
		protected var engineCore:FlashAppEngineCore;
		protected var doCheckLoadProgress:Boolean;
		protected var doCheckIfOnStage:Boolean;
		
		
		public function FlashAppEngine()
		{
			//trace("FlashAppEngine(" + arguments + ")");
			//var e:Error;
			
			/**
			init();
			startUp();
			/**
			try
			{
				init();
				startUp();
			}
			catch(e:Error)
			{
				trace(e + "\t" + e.getStackTrace());
				return;
			}
			
			afterStartUp();
			/**/
			
			preInit();
			init();
			
			//trace(model + "\t" + view + "\t" + controller);
		}
		
		
		protected function preInit():void
		{
			//...
		}
		private function init():void
		{
			//trace(this + ".init(" + arguments + ")");
			//trace(loaderInfo + "\t" + loaderInfo.bytesLoaded + "\t" + loaderInfo.bytesTotal);
			//trace("checkLoadProgress=" + checkLoadProgress);
			
			if(doCheckLoadProgress && !checkLoadProgress())
			{
				return;
			}
			
			if(doCheckIfOnStage && !checkIfOnStage())
			{
				return;
			}
			
			try
			{
				engineCore = new FlashAppEngineCore();
				afterInit();
				
				startUp();
			}
			catch(e:Error)
			{
				trace(e + "\t" + e.getStackTrace());
				return;
			}
			/**/
			
			afterStartUp();
		}
		protected function checkLoadProgress():Boolean
		{
			if(loaderInfo.bytesLoaded<loaderInfo.bytesTotal)
			{
				loaderInfo.addEventListener("complete", loadComplete);
				loaderInfo.addEventListener("progress", loadProgress);
				return false;
			}
			
			return true;
		}
		protected function loadProgress(event:*):void
		{
			//...
		}
		protected function loadComplete(event:*):void
		{
			loaderInfo.removeEventListener("complete", loadComplete);
			loaderInfo.removeEventListener("progress", loadProgress);
			
			init();
		}
		protected function checkIfOnStage():Boolean
		{
			if(stage)
				return true;
			
			this.addEventListener("addedToStage", handleAddedToStageEvent);
			return false;
		}
		protected function handleAddedToStageEvent(event:*):void
		{
			if(stage)
			{
				this.removeEventListener("addedToStage", handleAddedToStageEvent);
				init();
			}
		}
		protected function afterInit():void
		{
		}
		protected function startUp():Boolean
		{
			return engineCore.startUp(model, view, controller);
		}
		protected function afterStartUp():void
		{
			this.addChild(view);
			controller.startUp();
		}
		
		
		public static function get instance():FlashAppEngine
		{
			return FlashAppEngine(__instance);
		}
		/**
		 * AbstractEngine model, view, controller getters can't be overriden in as3, thus here is a trick.
		 */
		public function get model():FlashAppModel
		{
			return engineCore.model as FlashAppModel;
		}
		public function get view():FlashAppView
		{
			return engineCore.view as FlashAppView;
		}
		public function get controller():FlashAppController
		{
			return engineCore.controller as FlashAppController;
		}
		
	
		/**
		 * Returns a string describing an nstance.
		 */
		override public function toString():String
		{
			return "[com.bizmlib.framework.flashapp.FlashAppEngine]";
		}
	}
	
}